/*
 * Copyright (C) 2025 Tsingteng MicroSystem
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "nfa_base.h"
#include "nfa_wiredse_api.h"
#include "wiredse_main.h"
#include "nfc_osi_api.h"
#include "nci_feature.h"

/**
 * @brief wiredse模块对外接口
 * @file wiredse_api.c
 */
#if IS_FEATURE_ON(NCI_FEATURE_WIRED_SE)

extern tMUTEX g_wiredse_lock;
extern tWIREDSE_RESULT g_wiredse_result;
extern tAPDU last_ATR;
extern tWIREDSE_PROP wiredse_prop;

/**
 * @brief 发送apdu abort请求
 * @param atr 存放获取到的ATR的指针
 * @return 成功时返回NCI_STATUS_OK
 */
tNCI_STATUS nfa_wiredse_abort(void) {
    tNCI_STATUS status;
    status = wiredse_sm(WIREDSE_EVT_ABORT, NULL);
    if (NCI_STATUS_OK != status) {
        NFCLOG_E("send apdu abort failed. ret:%d", status);
        return status;
    }
    tNFC_STATUS nfc_status = osi_mutex_wait(&g_wiredse_lock, wiredse_prop.max_rapdu_wait_time);
    if ((NFC_STATUS_OK != nfc_status) && (NFC_STATUS_TIMEOUT != nfc_status)) {
        NFCLOG_E("wait wiredse lock failed");
        status = NCI_STATUS_EXT_GET_LOCK_FAILED;
        goto clean;
    }
    if (WIREDSE_EVT_RECV_ATR == g_wiredse_result.event) {
        NFCLOG_D("got ATR. len:%d", g_wiredse_result.content.atr.len);
        // 更新ATR缓存
        if (last_ATR.data) {
            osi_free(last_ATR.data);
        }
        last_ATR = g_wiredse_result.content.atr;
        // atr结果已转存给调用者，把全局result中的buffer标记为已释放
        g_wiredse_result.content.atr.data = NULL;
        g_wiredse_result.event = WIREDSE_EVT_UNKNOWN;
        status = NCI_STATUS_OK;
    } else {
        NFCLOG_E("apdu abort failed. got event:%d is_timeout:%d", g_wiredse_result.event, (NFC_STATUS_TIMEOUT == nfc_status));
        if (NFC_STATUS_TIMEOUT == nfc_status) {
            status = NCI_STATUS_EXT_TIMEOUT;
        } else {
            status = NCI_STATUS_EXT_FAILED;
        }
    }
clean:
    // 释放result
    wiredse_clean_result();
    if (NFC_STATUS_OK != osi_mutex_unlock(&g_wiredse_lock)) {
        NFCLOG_E("release wiredse lock failed");
    }
    if (NCI_STATUS_EXT_TIMEOUT == status) {
        wiredse_sm(WIREDSE_EVT_TIMEOUT, NULL); // 通知状态机操作超时
    }
    return status;
}

/**
 * @brief 获取ATR内容
 * @note 从缓存里面获取最近一次的ATR的内容（不会真正执行get ATR)
 *       调用者需要提供一个长度至少为HCI_EVT_ATR_LEN的buf
 * @param atr 用于存放ATR结果的指针
 * @return 成功时返回NCI_STATUS_OK
 */
tNCI_STATUS nfa_wiredse_get_atr(tAPDU atr) {
    tNCI_STATUS status;
    if (NFC_STATUS_OK != osi_mutex_lock(&g_wiredse_lock)) {
        NFCLOG_E("get wiredse lock failed");
        return NCI_STATUS_EXT_GET_LOCK_FAILED;
    }
    if (last_ATR.data) {
        if (!osi_memcpy_s(atr.data, atr.len, last_ATR.data, last_ATR.len)) {
            NFCLOG_E("memcpy failed");
            status = NCI_STATUS_EXT_COPY_FAILED;
            goto unlock;
        }
        status = NCI_STATUS_OK;
    } else {
        NFCLOG_E("no ATR found");
        status = NCI_STATUS_EXT_FAILED;
    }
unlock:
    if (NFC_STATUS_OK != osi_mutex_unlock(&g_wiredse_lock)) {
        NFCLOG_E("release wiredse lock failed");
    }
    return status;
}

/**
 * @brief 发送end apdu请求
 * @note end apdu操作不会有返回值，指令发送成功即认为执行成功
 * @return 成功时返回NCI_STATUS_OK
 */
tNCI_STATUS nfa_wiredse_end_apdu(void) {
    tNCI_STATUS status;
    status = wiredse_sm(WIREDSE_EVT_END_APDU, NULL);
    if (NCI_STATUS_OK != status) {
        NFCLOG_E("send end apdu failed. ret:%d", status);
        return status;
    }
    // end apdu不需要等待结果
    if (NFC_STATUS_OK != osi_mutex_unlock(&g_wiredse_lock)) {
        NFCLOG_E("release wiredse lock failed");
    }
    return status;
}

/**
 * @brief 发送APDU请求
 * @note 执行成功时由调用者释放rapdu->data内存
 * @param capdu 需要发送的APDU
 * @param rapdu 用于存放rAPDU的指针，其中rAPDU->data由此方法分配，由调用者释放
 * @return 成功时返回NCI_STATUS_OK
 */
tNCI_STATUS nfa_wiredse_send_apdu(tAPDU capdu, tAPDU *rapdu) {
    tNCI_STATUS status;
    status = wiredse_sm(WIREDSE_EVT_SEND_APDU, (tWIREDSE_MESSAGE_CONTENT *)&capdu);
    if (NCI_STATUS_OK != status) {
        NFCLOG_E("send apdu failed. ret:%d", status);
        return status;
    }
    tNFC_STATUS nfc_status = osi_mutex_wait(&g_wiredse_lock, wiredse_prop.max_rapdu_wait_time);
    if ((NFC_STATUS_OK != nfc_status) && (NFC_STATUS_TIMEOUT != nfc_status)) {
        NFCLOG_E("wait wiredse lock failed");
        status = NCI_STATUS_EXT_GET_LOCK_FAILED;
        goto clean;
    }
    if (WIREDSE_EVT_RECV_APDU == g_wiredse_result.event) {
        NFCLOG_D("got rAPDU. len:%d", g_wiredse_result.content.apdu.len);
        *rapdu = g_wiredse_result.content.apdu;
        // rapdu->data已转给调用者，标记结果为已处理
        g_wiredse_result.event = WIREDSE_EVT_UNKNOWN;
        g_wiredse_result.content.apdu.data = NULL;
        g_wiredse_result.content.apdu.len = 0;
        status = NCI_STATUS_OK;
    } else {
        NFCLOG_E("apdu exec failed. got event:%d is_timeout=%d", g_wiredse_result.event, (NFC_STATUS_TIMEOUT == nfc_status));
        if (NFC_STATUS_TIMEOUT == nfc_status) {
            status = NCI_STATUS_EXT_TIMEOUT;
        } else {
            status = NCI_STATUS_EXT_FAILED;
        }
    }
clean:
    // 释放result
    wiredse_clean_result();
    if (NFC_STATUS_OK != osi_mutex_unlock(&g_wiredse_lock)) {
        NFCLOG_E("release wiredse lock failed");
    }
    if (NCI_STATUS_EXT_TIMEOUT == status) {
        wiredse_sm(WIREDSE_EVT_TIMEOUT, NULL); // 通知状态机操作超时
    }
    return status;
}


// 以下是debug相关接口，仅用于测试用途
void nfa_wiredse_set_max_rapdu_wait_time_debug(uint32_t timeout_ms) {
    wiredse_prop.max_rapdu_wait_time = timeout_ms;
}

#endif // IS_FEATURE_ON(NCI_FEATURE_WIRED_SE)
